package com.sf.fy.uav.applet.config;

import com.sf.fy.uav.applet.order.controller.service.OrderService;
import com.sf.fy.uav.applet.order.controller.task.TaskController;
import com.sf.fy.uav.common.enums.ServicePrefixEnum;
import com.sf.fy.uav.common.request.common.IdRequest;
import com.sf.fy.uav.common.utils.RedisPrefixKey;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.Set;

/**
 * @author LTQ
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DelayQueue {


    @Value("${redis.dead:delayQueue}")
    private String DELAY_MESSAGE_QUEUE;

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private final RedisTemplate<String, String> redisTemplate;

    @Autowired
    private TaskController taskController;

    @Autowired
    private OrderService orderService;

    /**
     * 消息入队
     * 只要用户继续发起请求，就会继续延长时间戳的时间 直到用户一直没有请求后，然后到达指定时间给消费者进行消费
     * 如果有其他用户进来，那么这个队列会根据时间戳进行排序 排在前面的并且达到指定时间就先进行消费
     *
     * @param msg
     * @param time
     */
    public void pushQueue(String msg, Long time) {
        try {
            // 存的值是集合的主键 一般固定
            // 第二个是id 每个用户一个id
            // 第三个是根据什么进行排序，这里是根据时间戳，这里如果是同个key，那么会刷新同个key的时间戳并重新进行排序
            // 不同的key就是当前时间加10秒，也就是10秒后过期
            log.info("生产了消息" + msg + "生产时间 " + simpleDateFormat.format(System.currentTimeMillis()));
            redisTemplate.opsForZSet().add(ServicePrefixEnum.RESCUE + "." + DELAY_MESSAGE_QUEUE, msg, System.currentTimeMillis() + time);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 消息出队
     * 权重就是时间戳
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void pullQueue() {
        System.out.println("------------等待消费--------------" + simpleDateFormat.format(System.currentTimeMillis()));
        // 获取0-当前时间戳的范围的所有值
        Set<String> set = redisTemplate.opsForZSet().rangeByScore(ServicePrefixEnum.RESCUE + "." + DELAY_MESSAGE_QUEUE, 0, System.currentTimeMillis());
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String value = iterator.next();
            if (value.startsWith(ServicePrefixEnum.RESCUE.name())) {
                // 遍历取出每一个score
                Double score = redisTemplate.opsForZSet().score(ServicePrefixEnum.RESCUE + "." + DELAY_MESSAGE_QUEUE, value);
                if (!ObjectUtils.isEmpty(score)) {
                    // 达到时间进行消费 当前时间大于
                    if (System.currentTimeMillis() > score) {
                        // 移除该队列的值
                        redisTemplate.opsForZSet().remove(ServicePrefixEnum.RESCUE + "." + DELAY_MESSAGE_QUEUE, value);
                        log.info("消费了" + value + "消费时间 " + simpleDateFormat.format(System.currentTimeMillis()));
                        if (value.contains(ServicePrefixEnum.RESCUE + RedisPrefixKey.ORDER_COUNT_DOWN)) {
                            String orderId = value.replace(ServicePrefixEnum.RESCUE + RedisPrefixKey.ORDER_COUNT_DOWN, "");
                            //订单支付倒数结束
                            orderService.expireOrder(orderId);

                        } else if (value.contains(ServicePrefixEnum.RESCUE + RedisPrefixKey.SEND_NOTICE)) {
                            String orderId = value.replace(ServicePrefixEnum.RESCUE + RedisPrefixKey.SEND_NOTICE, "");
                            orderService.sendPaySuccessMsg(orderId);
                        }
                    }
                }
            }

        }
    }

}

